/*
 * Copyright (c) 2017 22420103@QQ.COM 版权所有
 */
package com.lehe.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.lehe.common.Contants;
import com.lehe.common.exceptions.LHException;
import com.lehe.dao.XHUserListDao;
import com.lehe.entry.UserInfoDto;
import com.lehe.entry.UserSessionDto;
import com.lehe.entry.xh.UserDto;
import com.lehe.service.impl.UserInfoService;
import com.lehe.wxpay.WXPay;
import com.lehe.wxpay.WXPayConfigImpl;
import com.lehe.wxpay.WXPayUtil;

/**
 * 微信授权后回调跳转的页面，也就是微信的入口URL
 *
 * @author 王丹
 * @since 2017-02-25
 */
@Controller
@RequestMapping("index")
public class IndexController extends Basecontroller {

    @Autowired
    private UserInfoService userInfoService;
    
    @Autowired
    private XHUserListDao xHUserListDao;

    /**
     * 正式环境入口-用户登录
     * @param code
     * @return http://admin.lehexinxi.com/forward.php
     * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxa79e12d33f38c86e&redirect_uri=http://mp.qpqpgame.com/index&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
     * http://www.qpqpgame.com/Admin_AgentManager/login.php
     * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf9dd51eb7319108c&redirect_uri=http://wx.qpqpgame.com/index&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
     * @throws LHException
     */
    @RequestMapping
    public String index(@RequestParam(value="code") String code) throws LHException {
        if(null == getUserSession()){
            Map<String, String> wxUserMap = userInfoService.invokeWxForUnionId(code);
            String wxUnionId = wxUserMap.get("wxUnionId");
            UserInfoDto userInfoDto = userInfoService.queryUserInfo(null, wxUnionId);
            
            
            
            if(null == userInfoDto){
                throw new LHException("您的微信号未注册");
            }
            
            List<UserDto> result = xHUserListDao.queryUserList(null, null, userInfoDto.getUserId(), null, null, null, null, null, null, null);
            if(result == null || result.isEmpty()){
            	throw new LHException("您的微信号未注册");
            }
            
            if(result.get(0).getUtype() == 0){
                throw new LHException("您的权限不是代理用户");
            }
            
            UserSessionDto sessionDto = new UserSessionDto();
            BeanUtils.copyProperties(userInfoDto, sessionDto);
            sessionDto.setWxOpenId(wxUserMap.get("wxOpenId"));
            session.setAttribute(Contants.SESSION_USER_KEY, sessionDto);
        }
        return "redirect:/main";
    }

    

    /**
     * 邀请码注册
     * @return
     * @throws LHException
     */
    @RequestMapping("regist/{userId}")
    public String regist(@RequestParam(value="code") String code,@PathVariable String userId,HttpServletRequest request,Model model) throws LHException {
    	Map<String, String> wxUserMap = userInfoService.invokeWxForUnionId(code);
    	//Map<String, String> wxUserMap = new HashMap<String,String>();
        String wxUnionId = wxUserMap.get("wxUnionId");
        String wxOpenId = wxUserMap.get("wxOpenId");
        String nickName = wxUserMap.get("nickName");
        String imgUrl = wxUserMap.get("imgUrl");
        String sex = wxUserMap.get("sex");
        String address = wxUserMap.get("address");
        //进行注册
        Map register = userInfoService.register(userId,wxUnionId,wxOpenId,nickName,imgUrl,sex,address,getIpAddr(request));
        String errorDescribe = (String)register.get("ErrorDescribe");
        System.out.println(errorDescribe);
        model.addAttribute("errorDescribe", errorDescribe);
        return "user/successJumper";
    }
    
    /**
    * 获取访问者IP
    * 
    * 在一般情况下使用Request.getRemoteAddr()即可，但是经过nginx等反向代理软件后，这个方法会失效。
    * 
    * 本方法先从Header中获取X-Real-IP，如果不存在再从X-Forwarded-For获得第一个IP(用,分割)，
    * 如果还不存在则调用Request .getRemoteAddr()。
    * 
    * @param request
    * @return
    */
    public String getIpAddr(HttpServletRequest request) {
	    try {
			String ip = request.getHeader("X-Real-IP");
			if (ip != null && !ip.trim().equals("") && !"unknown".equalsIgnoreCase(ip)) {
				return ip;
			}
			ip = request.getHeader("X-Forwarded-For");
			if (ip != null && !ip.trim().equals("") && !"unknown".equalsIgnoreCase(ip)) {
			    // 多次反向代理后会有多个IP值，第一个为真实IP。
			    int index = ip.indexOf(',');
			    if (index != -1) {
			    	return ip.substring(0, index);
			    } else {
			    	return ip;
			    }
			} else {
				return request.getRemoteAddr();
			}
		} catch (Exception e) {
			return null;
		}
    }
    
    
    /**
     * 测试环境入口-用户登录
     * @return
     * @throws LHException
     */
    @RequestMapping("test")
    public String test() throws LHException {
        UserSessionDto sessionDto = new UserSessionDto();
        sessionDto.setUserId(100109L);
        
        session.setAttribute(Contants.SESSION_USER_KEY, sessionDto);
        return "redirect:/main";
    }
    
    /**
     * 测试环境入口-用户登录
     * @return
     * @throws LHException
     */
    @RequestMapping("test/{userId}")
    public String testT(@PathVariable Long userId) throws LHException {
        UserSessionDto sessionDto = new UserSessionDto();
        sessionDto.setUserId(userId);
        session.setAttribute(Contants.SESSION_USER_KEY, sessionDto);
        return "redirect:/main";
    }
    
    @RequestMapping("down")
    public String down(String errorDescribe,Model model) throws LHException {
        model.addAttribute("errorDescribe", errorDescribe);
    	return "user/registSuccess";
    }

    @RequestMapping("wxpaynotify")
    public String wxpaynotify(HttpServletRequest request, HttpServletResponse response){
        /*支付完成后，微信会把相关支付结果和用户信息发送给商户，商户需要接收处理，并返回应答。
        对后台通知交互时，如果微信收到商户的应答不是成功或超时，微信认为通知失败，微信会通过一定的策略定期重新发起通知，尽可能提高通知的成功率，但微信不保证通知最终能成功。 （通知频率为15/15/30/180/1800/1800/1800/1800/3600，单位：秒）
        注意：同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
        推荐的做法是，当收到通知进行处理时，首先检查对应业务数据的状态，判断该通知是否已经处理过，如果没有处理过再进行处理，如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前，要采用数据锁进行并发控制，以避免函数重入造成的数据混乱。
        特别提醒：商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致，防止数据泄漏导致出现“假通知”，造成资金损失。
        技术人员可登进微信商户后台扫描加入接口报警群。SUCCESS/FAIL*/
        String respStr = "<xml>" +
                "  <return_code><![CDATA[FAIL]]></return_code>" +
                "  <return_msg><![CDATA[签名错误]]></return_msg>" +
                "</xml>";
        try{
            String notifyData = getRequestContent(request);
            logger.info("接收微信支付结果通知报文：{}" , notifyData);
            WXPayConfigImpl config = new WXPayConfigImpl();
            WXPay wxpay = new WXPay(config);
            //WXPay wxpay = new WXPay(config, WXPayConstants.SignType.MD5, true);
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
            logger.info("接收微信支付结果转换后数据：{}" , notifyMap);
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
                // 签名正确
                // 进行处理。
                // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
                respStr = "<xml>" +
                        "  <return_code><![CDATA[SUCCESS]]></return_code>" +
                        "  <return_msg><![CDATA[OK]]></return_msg>" +
                        "</xml>";
            }else {
                // 签名错误，如果数据里没有sign字段，也认为是签名错误
            }
        }catch (Exception e){
            logger.error("接收微信支付结果通知异常", e);
            respStr = "<xml>" +
                    "  <return_code><![CDATA[FAIL]]></return_code>" +
                    "  <return_msg><![CDATA[业务处理错误]]></return_msg>" +
                    "</xml>";
        }
        try {
            logger.info("接收微信支付结果应答报文：{}" , respStr);
            makeResponse(response, "text/html", respStr);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("应答微信支付结果异常", e);
        }
        return null;
    }
}
